<?php
namespace alpay;

class Alpay
{
    //https://open.alipay.com 账户中心->密钥管理->开放平台密钥，填写添加了电脑网站支付的应用的APPID
    protected $appId = '2019021963256193';
    //付款成功后的异步回调地址
    protected $notifyUrl = '';
    protected $charset = 'utf8';
    //私钥值---商户私钥
    protected $rsaPrivateKey = 'MIIEogIBAAKCAQEA0XcguyDhXuRmtO46ikBe51N+f6VnISRw0YpbBGNAF6qBm6ec+l87XWUyC1E5s6phki/vmSvhC4pZ9AcWjEoidxqsrfgh+vWQPOdDJ4VtR1E8cV7n39la+B2V6d97iTHIF7iCdj4Bu7Y/ZtBL1sq9cNxW/w7ZW25chFflundwe7NGzQ3cRqcbH2lNrvqLO2NokYovcqrv69i2GBHrZfpX7qHIeL/arshGf27tIc+OwVX2rYi3lsrGRY6QX/4gqSCA8OJpryLbqfmkihGKujP/V6oFgWrOi1GpI0GBKZN1sy+lxW+3yRW+r3+Ep4f2TNE/ZYJkDU5vRNC4QRgDBjOqiQIDAQABAoIBADJGd5Kyl6VhCM3QiDh6rsyzG5+joZcw2etRW/s3n0CO6kDkACeQB/2otlRFEKZw9K5T1xxajc9pS6HouZ6+hHs16dBvyCgmHJKhp1qrCcmeU/WaI+l0kAMRhtP1kf8h9bbL0HR0+ZGGcr1IrYtGaiXWnQLnG4B4grg5KKiS1mq586+Hx4Zu6JUhrdNLvefdrLYGb5e8L2Ti+oT5m9WMxJuxgO/cfh5Uj2qpGNSs9h+A14YXT/ligBO826YgCKobghYmKXQxbOYExOS4hwC7kZPK1F4KyLQGtakWCHY3UEDYfAb2pP87+GRfgkqaWUOr9d11yBFy9HZFp+ypvo6ZwQECgYEA8xWeMFXx1N/vDEycaJTOit90pC/LLgu8cVa33Va0xRbzUdQeD9d1QfD3XoC/A4Y7s8CmDTf+6mYRPOPWYI+FsX8cpOh2fZQhJBbhN7BT+1ooB2kPS6EObpfYYGDr7nEaqR9YywHyfRIhsHaC+wjNgPa9VfU0J7QR3KQvhtzJ0lkCgYEA3Jg67LW4xfAmlpUWJjzNn15hnito3ngDBR9JcQ5AwPUSWM5FlKIYXj4P3QtGubQjOnKE49dJNwHQVjP/q10kQ0KjHDKXpf7nZPyWskHZuoEhYjws69c7GLJYNbV8jkDuRYkcGdP6m7zw4Cr0ctny/REhma2NYA4XQiukX0Cds7ECgYAqnD9+eZJKnnZo0YUZT/xkm4b2wOn8yFHgDDNuuSQ26C7+yQ/79ui3BmZWSnsxQvZ0K/DvoEEvFXUwF0Ac7QuicYWz4ovit3SXvur7uA0Aom0h32iu+Sxudm+XdWXmBi2GN9h4vX6kLel55UxQdNqRIK9PwgvCae43nxA1s74tAQKBgC+nu2MTxv0L6moxfv13uTwqmZAf9KHK72wV3DnOSHLm/rWsqh93/Seu5KJuIzNPFSU1RDwscCav/5//z8Xnc0QMi0w2Kci0jqykXLHZw/2kk9+y/Elez+d/78p6kJPytwbSnf1+a+9lG+xxmymMqA+/ubCHa7lKkf+7ieECBo+hAoGAVOu7Dqgi1T25e5xUwlxJbhZPKas4tnuH5Lv0gKb6cZePIiyj3XPc9fkEk0CPVB/xzOzUEZaUu41Zzya7o65arHYXqBvIdtCVaKJh0sneGrYWFa+Rah6tI0w2n/vnOJCmWc/44pA+u0X6ApzLmmAy6GBrsF8Fi6UwEgs8xUoKqns=';
    //订单价格 单位 元
    protected $totalFee;
    //jsapi支付订单流水号
    protected $outTradeNo;
    //订单标题
    protected $orderName;
    protected $scope;
    // 购买者的userid
    protected $buyerId;
    protected $authCode;

    public function setTotalFee($payAmount)
    {
        $this->totalFee = $payAmount;
    }
    public function setOutTradeNo($outTradeNo)
    {
        $this->outTradeNo = $outTradeNo;
    }
    public function setOrderName($orderName)
    {
        $this->orderName = $orderName;
    }
    public function setScope($scope)
    {
        $this->scope = $scope;
    }
    public function setBuyerId($buyerId)
    {
        $this->buyerId = $buyerId;
    }
    public function setAuthCode($authCode)
    {
        $this->authCode = $authCode;
    }
    /**
     * 获取orderStr
     * @return array
     */
    public function createOrder()
    {
        //请求参数
        $requestConfigs = array(
            'out_trade_no' => $this->outTradeNo,
            //单位 元
            'total_amount' => $this->totalFee,
            //订单标题
            'subject' => $this->orderName,
            //购买者的userid
            'buyer_id' => $this->buyerId,
             //订单允许的最晚付款时间，逾期将关闭交易。取值范围：1m～15d。m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下都在0点关闭）。 该参数数值不接受小数点， 如 1.5h，可转换为 90m
            'timeout_express' => '2h',
        );
        $commonConfigs = array(
            //公共参数
            'app_id' => $this->appId,
            'method' => 'alipay.trade.create',             //接口名称
            'format' => 'JSON',
            'charset' => $this->charset,
            'sign_type' => 'RSA2',
            'timestamp' => date('Y-m-d H:i:s'),
            'version' => '1.0',
            'notify_url' => $this->notifyUrl,
            'biz_content' => json_encode($requestConfigs),
        );
        $commonConfigs["sign"] = $this->generateSign($commonConfigs, $commonConfigs['sign_type']);
        $result = $this->curlPost('https://openapi.alipay.com/gateway.do', $commonConfigs);
        return json_decode($result, true);
    }
    public function generateSign($params, $signType = "RSA")
    {
        return $this->sign($this->getSignContent($params), $signType);
    }
    protected function sign($data, $signType = "RSA")
    {
        $priKey = $this->rsaPrivateKey;
        $res = "-----BEGIN RSA PRIVATE KEY-----\n" . wordwrap($priKey, 64, "\n", true) . "\n-----END RSA PRIVATE KEY-----";
        ($res) or die('您使用的私钥格式错误，请检查RSA私钥配置');
        if ("RSA2" == $signType) {
            //OPENSSL_ALGO_SHA256是php5.4.8以上版本才支持
            openssl_sign($data, $sign, $res, OPENSSL_ALGO_SHA256);
        } else {
            openssl_sign($data, $sign, $res);
        }
        $sign = base64_encode($sign);
        return $sign;
    }
    /**
     * 校验$value是否非空
     *  if not set ,return true;
     *    if is null , return true;
     **/
    protected function checkEmpty($value)
    {
        if (!isset($value))
            return true;
        if ($value === null)
            return true;
        if (trim($value) === "")
            return true;
        return false;
    }
    public function getSignContent($params)
    {
        ksort($params);
        $stringToBeSigned = "";
        $i = 0;
        foreach ($params as $k => $v) {
            if (false === $this->checkEmpty($v) && "@" != substr($v, 0, 1)) {
                // 转换成目标字符集
                $v = $this->characet($v, $this->charset);
                if ($i == 0) {
                    $stringToBeSigned .= "$k" . "=" . "$v";
                } else {
                    $stringToBeSigned .= "&" . "$k" . "=" . "$v";
                }
                $i++;
            }
        }
        unset($k, $v);
        return $stringToBeSigned;
    }
    /**
     * 转换字符集编码
     * @param $data
     * @param $targetCharset
     * @return string
     */
    function characet($data, $targetCharset)
    {
        if (!empty($data)) {
            $fileType = $this->charset;
            if (strcasecmp($fileType, $targetCharset) != 0) {
                $data = mb_convert_encoding($data, $targetCharset, $fileType);
                //$data = iconv($fileType, $targetCharset.'//IGNORE', $data);
            }
        }
        return $data;
    }
    public function buildOrderStr($data)
    {
        return http_build_query($data);
    }
    public function curlPost($url = '', $postData = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    /**
     * 获取access_token和user_id
     */
    public function getToken()
    {
        //通过code获得access_token和user_id
        if (!isset($_GET['auth_code'])) {
            //触发微信返回code码
            $scheme = 'http://';
            $uri = $_SERVER['PHP_SELF'] . $_SERVER['QUERY_STRING'];
            if ($_SERVER['REQUEST_URI']) $uri = $_SERVER['REQUEST_URI'];
            $baseUrl = $scheme . $_SERVER['HTTP_HOST'] . $uri;
            $url = $this->__CreateOauthUrlForCode($baseUrl);
            Header("Location: $url");
            exit();
        } else {
            //获取code码，以获取openid
            $this->setAuthCode($_GET['auth_code']);
            return $this->doAuth();
        }
    }
    /**
     * 构造获取token的url连接
     * @param string $redirectUrl 服务器回跳的url，需要url编码
     * @return 返回构造好的url
     */
    private function __CreateOauthUrlForCode($redirectUrl)
    {
        $urlObj["app_id"] = $this->appId;
        $urlObj["redirect_uri"] = urlencode($redirectUrl);
        $urlObj["scope"] = $this->scope;
        $urlObj["state"] = 'alpay';
        $bizString = $this->ToUrlParams($urlObj);
        return "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?" . $bizString;
    }
    /**
     * 拼接签名字符串
     * @param array $urlObj
     * @return 返回已经拼接好的字符串
     */
    private function ToUrlParams($urlObj)
    {
        $buff = "";
        foreach ($urlObj as $k => $v) {
            if ($k != "sign") $buff .= $k . "=" . $v . "&";
        }
        $buff = trim($buff, "&");
        return $buff;
    }
    /**
     * 获取access_token和user_id
     * @return array
     */
    public function doAuth()
    {
        $commonConfigs = array(
            //公共参数
            'app_id' => $this->appId,
            'method' => 'alipay.system.oauth.token',//接口名称
            'format' => 'JSON',
            'charset' => $this->charset,
            'sign_type' => 'RSA2',
            'timestamp' => date('Y-m-d H:i:s'),
            'version' => '1.0',
            'grant_type' => 'authorization_code',
            'code' => $this->authCode,
        );
        $commonConfigs["sign"] = $this->generateSign($commonConfigs, $commonConfigs['sign_type']);
        //沙箱环境需要修改
        $result = $this->curlPost('https://openapi.alipay.com/gateway.do', $commonConfigs);
        $result = iconv('GBK', 'UTF-8', $result);
        return json_decode($result, true);
    }
}